using System;
using System.Diagnostics.Contracts;
using System.Linq;
using Boggle.Net.Model;
using Caliburn.Micro;

namespace Boggle.Net.ViewModels
{
    public sealed class TrayCell : PropertyChangedBase
    {
        private readonly Tray _tray;
        private readonly Tray.Location _location;

        private Selection<TrayCell> _selection;

        public TrayCell(Tray tray, Tray.Location location)
        {
            Contract.Requires<ArgumentNullException>(tray != null);

            _tray = tray;
            _location = location;
        }

        public char Letter
        {
            get { return _tray.LetterAt(Location); }
        }

        public Tray.Location Location
        {
            get { return _location; }
        }

        public bool IsEnabled
        {
            get
            {
                if (Selection == null) return false;

                if (!Selection.Any()) return true;

                var lastCell = Selection.Last();
                return lastCell == this || lastCell.Location.NeighbouringLocations.Contains(Location);
            }
        }

        public bool IsSelected
        {
            get { return Selection != null && Selection.Contains(this); }
            set
            {
                var isSelected = IsSelected;
                if (value == isSelected || !IsEnabled) return;

                if (!isSelected)
                    Selection.Push(this);
                else if (Selection.Last() == this)
                    Selection.Pop();
            }
        }

        internal Selection<TrayCell> Selection
        {
            get { return _selection; }
            set
            {
                if (value == Selection) return;

                if (Selection != null) Selection.Changed -= OnSelectionChanged;
                _selection = value;
                if (Selection != null) Selection.Changed += OnSelectionChanged;

                NotifyOfPropertyChange(() => IsSelected);
                NotifyOfPropertyChange(() => IsEnabled);
            }
        }

        private void OnSelectionChanged(object sender, EventArgs e)
        {
            NotifyOfPropertyChange(() => IsSelected);
            NotifyOfPropertyChange(() => IsEnabled);
        }
    }
}